﻿using System.Diagnostics;
using System.Diagnostics.Contracts;

namespace DaveSexton.Labs
{
	/// <summary>
	/// Represents an <see cref="ILab"/> host.
	/// </summary>
	[ContractClass(typeof(ILabHostContract))]
	public interface ILabHost
	{
		/// <summary>
		/// Gets or sets the application's title.
		/// </summary>
		string ApplicationTitle { get; set; }

		/// <summary>
		/// Gets or sets a value indicating whether the current lab is selectable.
		/// </summary>
		bool CanChangeLab { get; set; }

		/// <summary>
		/// Loads all labs in the specified <paramref name="category"/>.
		/// </summary>
		/// <param name="category">The category from which to load labs.</param>
		void LoadLabs(LabCategory category);

		/// <summary>
		/// Sets the specified <paramref name="lab"/> as the current lab.
		/// </summary>
		/// <param name="lab">The <see cref="Lab"/> to be set as the current lab.</param>
		void SetCurrentLab(Lab lab);

		/// <summary>
		/// Writes the specified message to the console output.
		/// </summary>
		/// <param name="message">The message to be written.</param>
		/// <param name="eventType">The type of the message.</param>
		void Write(string message, TraceEventType eventType);

		/// <summary>
		/// Writes the specified message and a new line to the console output.
		/// </summary>
		/// <param name="message">The message to be written.</param>
		/// <param name="eventType">The type of the message.</param>
		void WriteLine(string message, TraceEventType eventType);

		/// <summary>
		/// Clears the console output.
		/// </summary>
		void Clear();
	}

	[ContractClassFor(typeof(ILabHost))]
	internal abstract class ILabHostContract : ILabHost
	{
		public string ApplicationTitle
		{
			get
			{
				return null;
			}
			set
			{
			}
		}

		public bool CanChangeLab
		{
			get;
			set;
		}

		public void LoadLabs(LabCategory category)
		{
			Contract.Requires(category != null);
			Contract.Requires(category.IsRoot);
		}

		public void SetCurrentLab(Lab lab)
		{
			Contract.Requires(lab != null);
			Contract.Requires(CanChangeLab);
		}

		public void Write(string message, TraceEventType eventType)
		{
		}

		public void WriteLine(string message, TraceEventType eventType)
		{
		}

		public void Clear()
		{
		}
	}
}
